#include "GuardDog.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"
#include "../SGD Wrappers/SGD_AudioManager.h"
#include "DestroyObjectMessage.h"
#include "GameplayState.h"
#include "BehaviorManager.h"
#include "BaseBehavior.h"
#include "SpawnDoor.h"
#include "Player.h"
#include "../SGD Wrappers/SGD_Event.h"

GuardDog::GuardDog() : Listener(this)
{
	m_FieldOfView.SetOwner(this);
	RegisterForEvent("ALARM_OFF");
	RegisterForEvent("LOST_TARGET");
	RegisterForEvent("TARGET_FOUND");
	RegisterForEvent("STUNNED");
	RegisterForEvent("PAUSE");
	RegisterForEvent("UNPAUSE");

	animation.m_fCurrDuration = 0;
	animation.m_nCurrFrame = 0;
	animation.m_strCurrAnimation = "dog";

	barking = &GameplayState::GetInstance()->dogBarking;
	sniffing = &GameplayState::GetInstance()->dogSniffing;
	voice = SGD::INVALID_HANDLE;
	//voice = SGD::AudioManager::GetInstance()->PlayAudio(*sniffing, true);
	//SGD::AudioManager::GetInstance()->SetVoiceVolume(voice, 0);

	m_nAIState = PATROL;
	RetrieveBehavior("runTo");

}
GuardDog::~GuardDog()
{
	
	UnregisterFromEvent("ALARM_OFF");
	UnregisterFromEvent("LOST_TARGET");
	UnregisterFromEvent("TARGET_FOUND");
	UnregisterFromEvent("STUNNED");
	UnregisterFromEvent("PAUSE");
	UnregisterFromEvent("UNPAUSE");

}

/*virtual*/ void GuardDog::Update(float dt)	 /*override*/
{
	SGD::AudioManager* pAudio = SGD::AudioManager::GetInstance();


	if (m_tStunTimer.Update(dt))
	{
		//if ((m_pTarget->GetPosition() - m_ptPosition).ComputeLength() < 1000.0f && SGD::AudioManager::GetInstance()->IsVoiceValid(voice))
		//	SGD::AudioManager::GetInstance()->SetVoiceVolume(voice, 75);
		//else if ((m_pTarget->GetPosition() - m_ptPosition).ComputeLength() >= 1000.0f && SGD::AudioManager::GetInstance()->IsVoiceValid(voice))
		//	SGD::AudioManager::GetInstance()->SetVoiceVolume(voice, 0);

		if (currBehavior != nullptr)
		{
			if (m_nAIState == PATROL)
			{
				this->SetMoveSpeed(128.0f);

				if (currBehavior->Update(dt, this, *navGraph->GetVertexElement(currPath[m_nCurrPathNode])))
				{
					m_nCurrPathNode++;
					if (m_nCurrPathNode == currPath.size())
					{
						m_nCurrPathNode = 0;
						m_nCurrWaypoint++;
						if (m_nCurrWaypoint == m_vWayPoints.size())
							m_nCurrWaypoint = 0;

						navGraph->FindPath(m_vWayPoints[m_nCurrWaypoint], homeNode, currPath);
						m_nAIState = GO_HOME;


						// switch audio to sniffing
						/*if (pAudio->IsVoiceValid(voice))
						{
							if (pAudio->IsAudioPlaying(*barking) == true)
								pAudio->StopAudio(*barking);

							if (pAudio->IsAudioPlaying(*sniffing) == false)
								voice = pAudio->PlayAudio(*sniffing, false);

							pAudio->SetVoiceVolume(voice);
						}*/
					}
				}
			}
			else if (m_nAIState == GO_HOME)
			{
				this->SetMoveSpeed(128.0f);

				if (currBehavior->Update(dt, this, *navGraph->GetVertexElement(currPath[m_nCurrPathNode])))
				{
					m_nCurrPathNode++;
					if (m_nCurrPathNode == currPath.size())
					{
						SGD::AudioManager::GetInstance()->StopAudio(*barking);
						DestroyObjectMessage* dMsg = new DestroyObjectMessage{ this };

						dMsg->QueueMessage();
						dMsg = nullptr;
					}
				}
			}
			else if (m_nAIState == SEARCHING)
			{
				this->SetMoveSpeed(128.0f);

				if (currBehavior->Update(dt, this, *navGraph->GetVertexElement(currPath[m_nCurrPathNode])))
				{
					m_nCurrPathNode++;
					if (m_nCurrPathNode == currPath.size())
					{
						m_nCurrPathNode = 0;
						m_nCurrWaypoint++;
						if (m_nCurrWaypoint == m_vWayPoints.size())
							m_nCurrWaypoint = 0;
						unsigned int closestNodeToMe;

						float distanceToNode = 70000;
						float distanceToLastKnown = 70000;
						for (unsigned int i = 0; i < navGraph->size(); i++)
						{

							SGD::Point temp = *navGraph->GetVertexElement(i);
							float newDistance = (temp - m_ptPosition).ComputeLength();

							if (newDistance < distanceToNode)
							{
								distanceToNode = newDistance;
								closestNodeToMe = i;
							}

						}
						navGraph->FindPath(closestNodeToMe, m_vWayPoints[m_nCurrWaypoint], currPath);
						m_nAIState = PATROL;


						// switch audio to sniffing
						/*if (pAudio->IsVoiceValid(voice))
						{
							if (pAudio->IsAudioPlaying(*barking) == true)
								pAudio->StopAudio(*barking);

							if (pAudio->IsAudioPlaying(*sniffing) == false)
								voice = pAudio->PlayAudio(*sniffing, false);

							pAudio->SetVoiceVolume(voice);
						}*/
					}
				}
			}
			else if (m_nAIState == ATTACK)
			{

			}
			else if (m_nAIState == ALERT)
			{
				this->SetMoveSpeed(320.0f);
				currBehavior->Update(dt, this, m_pTarget->GetPosition());
			}
			else if (m_nAIState == WAIT)
				currBehavior->Update(dt, this, SGD::Point());

		}


		EnemyUnit::Update(dt);
	}
	
}

/*virtual*/ void GuardDog::HandleEvent(const SGD::Event* pEvent)
{
	SGD::AudioManager* pAudio = SGD::AudioManager::GetInstance();

	if (pEvent->GetEventID() == "ALARM_OFF")
	{
		navGraph->FindPath(m_vWayPoints[m_nCurrWaypoint], homeNode, currPath);

		m_nAIState = GO_HOME;
		RetrieveBehavior("runTO");
	}
	if (pEvent->GetEventID() == "LOST_TARGET")
	{
		m_ptLastKnownPos = m_pTarget->GetPosition();
		unsigned int closestNodeToMe;
		unsigned int closestNodeToPlayer;

		float distanceToNode = 70000;
		float distanceToLastKnown = 70000;
		for (unsigned int i = 0; i < navGraph->size(); i++)
		{

			SGD::Point temp = *navGraph->GetVertexElement(i);
			float newDistance = (temp - m_ptPosition).ComputeLength();

			if (newDistance < distanceToNode)
			{
				distanceToNode = newDistance;
				closestNodeToMe = i;
			}

		}

		for (unsigned int i = 0; i < navGraph->size(); i++)
		{

			SGD::Point temp = *navGraph->GetVertexElement(i);
			float newDistance = (temp - m_ptLastKnownPos).ComputeLength();

			if (newDistance < distanceToLastKnown)
			{
				distanceToLastKnown = newDistance;
				closestNodeToPlayer = i;
			}

		}

		m_nAIState = SEARCHING;
		navGraph->FindPath(closestNodeToMe, closestNodeToPlayer, currPath);
		m_nCurrPathNode = 0;

		RetrieveBehavior("runTo");
	}
	else if (pEvent->GetEventID() == "TARGET_FOUND")
	{
		m_nAIState = ALERT;
		RetrieveBehavior("runTo");

		// barking starts
		/*if (pAudio->IsVoiceValid(voice))
		{
			if (pAudio->IsAudioPlaying(*sniffing) == true)
				pAudio->StopAudio(*sniffing);

			if (pAudio->IsAudioPlaying(*barking) == false)
				voice = pAudio->PlayAudio(*barking, false);

			pAudio->SetVoiceVolume(voice);
		}*/
	}
	else if (pEvent->GetEventID() == "STUNNED")
	{
		// barking stops
		/*if (pAudio->IsVoiceValid(voice))
		{
			if (pAudio->IsAudioPlaying(*sniffing) == true)
				pAudio->StopAudio(*sniffing);

			if (pAudio->IsAudioPlaying(*barking) == true)
				pAudio->StopAudio(*barking);


			pAudio->SetVoiceVolume(voice);
		}*/


		m_tStunTimer.AddTime(5.0f);
		unsigned int closestNodeToMe;
		unsigned int closestNodeToPlayer;

		float distanceToNode = 70000;
		float distanceToLastKnown = 70000;
		for (unsigned int i = 0; i < navGraph->size(); i++)
		{

			SGD::Point temp = *navGraph->GetVertexElement(i);
			float newDistance = (temp - m_ptPosition).ComputeLength();

			if (newDistance < distanceToNode)
			{
				distanceToNode = newDistance;
				closestNodeToMe = i;
			}

		}

		for (unsigned int i = 0; i < navGraph->size(); i++)
		{

			SGD::Point temp = *navGraph->GetVertexElement(i);
			float newDistance = (temp - m_ptLastKnownPos).ComputeLength();

			if (newDistance < distanceToLastKnown)
			{
				distanceToLastKnown = newDistance;
				closestNodeToMe = i;
			}

		}

		m_nAIState = SEARCHING;
		navGraph->FindPath(closestNodeToMe, closestNodeToPlayer, currPath);
		m_nCurrPathNode = 0;

		RetrieveBehavior("runTo");
	}
	else if (pEvent->GetEventID() == "PAUSE")
	{
		//if (SGD::AudioManager::GetInstance()->IsVoiceValid(voice))
		//	SGD::AudioManager::GetInstance()->PauseVoice(voice, true);
	}


	else if (pEvent->GetEventID() == "UNPAUSE")
	{
		//if (SGD::AudioManager::GetInstance()->IsVoiceValid(voice))
		//	SGD::AudioManager::GetInstance()->PauseVoice(voice, false);

	}
	
}
/*virtual*/ void GuardDog::HandleCollision(const IBase* pOther) /*override*/
{
	if (pOther->GetType() == OBJ_PLAYER)
	{
		m_nAIState = ALERT;
		RetrieveBehavior("hostile");

	}
	else if (pOther->GetType() == OBJ_TRIGGER || pOther->GetType() == OBJ_PLAYERCOLLISION)
	{

	}
	else
		MovingObject::HandleCollision(pOther);
}

void GuardDog::RetrieveBehavior(std::string name)
{

	if (currBehavior != nullptr)
	{
		currBehavior = nullptr;
	}
	currBehavior = BehaviorManager::GetInstance()->GetBehaviors()[name];
}

/*virtual*/ void GuardDog::Attack() /*override*/
{
	m_vtVelocity *= 2.0f;
	m_nAIState = ATTACK;
}


void GuardDog::SetOwner(SpawnDoor* owner)
{
	if (m_pOwner != nullptr)
	{
		m_pOwner->Release();
		m_pOwner = nullptr;
	}
	m_pOwner = owner;
}
